﻿using Ongoal.Quotation.Common;
using Ongoal.Quotation.Common;
using Ongoal.Quotation.Model;
using Ongoal.Quotation.Service;
using Ongoal.Quotation.Service.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ongoal.Quotation.Service
{
    /// <summary>
    /// 登录相关服务实现
    /// </summary>
    public class LoginService : ServiceBase, ILoginService
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public LoginService():base()
        { 
        }

        /// <summary>
        /// 检查用户
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public UserInfo LoginCheck(string userName, string password,string ip)
        {
            var dbclient = this.Db.GetDbContext(string.Empty);
            //实现去数据库验证用户名密码，如果不匹配，直接throw 异常
            var sysUser = dbclient.Queryable<T_Sys_UserInfo>().Where(x => x.UserName == userName && x.LoginEnable == (int)ELoginEnable.Enable).First();
            if (sysUser == null || sysUser.LoginEnable == (int)ELoginEnable.Disable)
            {
                dbclient.Insertable<T_LoginLog>(new T_LoginLog()
                {
                    UserID = -1,
                    LoginUserName = userName,
                    LoginTime = DateTime.Now,
                    IPAddress = ip,
                    LoginResultType = (int)LoginResultType.UnKnownUser,
                    Remark = "用户不存在或者不可登录"
                }).ExecuteCommand();
                throw new Exception("用户不存在或者不可登录");
            }
            else
            {
                if (sysUser.IsLocked == (int)ELockState.Locked)
                {
                    dbclient.Insertable<T_LoginLog>(new T_LoginLog()
                    {
                        UserID = sysUser.ID,
                        LoginUserName = userName,
                        LoginTime = DateTime.Now,
                        IPAddress = ip,
                        LoginResultType = (int)LoginResultType.Fail,
                        Remark = "账号已经被锁定，请联系管理员解锁"
                    }).ExecuteCommand();

                    throw new Exception("账号已经被锁定，请联系管理员解锁");
                }
                if (sysUser.Password != Des.Encrypt(password))
                {
                    var errorCount = 1;
                    var limitCount = this.Config!.GetCfgValue<AuthSetting>("AuthSetting")!.LockLimit > 0 ? this.Config!.GetCfgValue<AuthSetting>("AuthSetting")!.LockLimit : 5;
                    if (this.Redis!.Exists($"LOGIN:ERROR:U_{sysUser.UserName.ToUpper()}"))
                    {
                        errorCount = this.Redis.Get<int>($"LOGIN:ERROR:U_{sysUser.UserName.ToUpper()}") + 1;
                    }
                    this.Redis.Set($"LOGIN:ERROR:U_{sysUser.UserName.ToUpper()}", errorCount, 30 * 60);
                    if (errorCount > limitCount)
                    {
                        sysUser.IsLocked = (int)ELockState.Locked;
                        sysUser.LockTime = DateTime.Now;
                        dbclient.Updateable<T_Sys_UserInfo>(sysUser).ExecuteCommand();
                        dbclient.Insertable<T_LoginLog>(new T_LoginLog()
                        {
                            UserID = sysUser.ID,
                            LoginUserName = userName,
                            LoginTime = DateTime.Now,
                            IPAddress = ip,
                            LoginResultType = (int)LoginResultType.Lock,
                            Remark = "尝试登录次数过多，账号已经被锁定，请联系管理员解锁"
                        }).ExecuteCommand();
                        throw new Exception("尝试登录次数过多，账号已经被锁定，请联系管理员解锁");
                    }
                    dbclient.Insertable<T_LoginLog>(new T_LoginLog()
                    {
                        UserID = sysUser.ID,
                        LoginUserName = userName,
                        LoginTime = DateTime.Now,
                        IPAddress = ip,
                        LoginResultType = (int)LoginResultType.Fail,
                        Remark = $"用户名密码不正确,登录{limitCount}次账号将自动锁定(已失败{errorCount}次)"
                    }).ExecuteCommand();
                    throw new Exception($"用户名密码不正确,登录{limitCount}次账号将自动锁定(已失败{errorCount}次)");
                }
                sysUser.LastLoginTime = DateTime.Now;
                sysUser.LoginTimes += 1;
                dbclient.Updateable<T_Sys_UserInfo>(sysUser).ExecuteCommand();
                dbclient.Insertable<T_LoginLog>(new T_LoginLog()
                {
                    UserID = sysUser.ID,
                    LoginUserName = userName,
                    LoginTime = DateTime.Now,
                    IPAddress = ip,
                    LoginResultType = (int)LoginResultType.Success,
                    Remark = "登录成功"
                }).ExecuteCommand();
                return new UserInfo()
                {
                    UserCode = sysUser.UserCode,
                    UserID = sysUser.ID,
                    UserName = sysUser.UserName,
                    UserType = sysUser.UserType,
                    AvatarUrl = sysUser.AvatarUrl,
                    DisplayName = sysUser.DisplayName,
                    Birthday = sysUser.Birthday,
                    Email = sysUser.Email,
                    Mobile = sysUser.Mobile,
                    QQ = sysUser.QQ,
                    LastLoginTime = DateTime.Now,
                    LoginTimes = sysUser.LoginTimes,
                    Sex = sysUser.Sex                    
                };
            }
        }

    }
}
